/**
 * vite.config.ts
 */
import path from "node:path";
import { fileURLToPath } from "node:url";
// ----------------------------------------------------------------------------
import chalk from "chalk";
import { defineConfig } from "vite";
import { loadEnv, type UserConfig, type ConfigEnv } from "vite";
// ----------------------------------------------------------------------------
// Vite Plugins - 1
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import vueDevTools from "vite-plugin-vue-devtools";
// ----------------------------------------------------------------------------
// Vite Plugins - 2
// import { createHtmlPlugin } from "vite-plugin-html"
// import { createSvgIconsPlugin } from "vite-plugin-svg-icons"
// import { viteStaticCopy } from "vite-plugin-static-copy"
// ----------------------------------------------------------------------------
// const appRoot = () => fileURLToPath(new URL("./", import.meta.url))
const AppRoot = path.resolve(process.cwd(), ""); // app root
const SRC = path.resolve(AppRoot, "src");
const OutDir = path.resolve(AppRoot, "dist");
const EnvDir = path.resolve(AppRoot, "env");
const CacheDir = path.resolve(AppRoot, "cache");
const PublicDir = path.resolve(AppRoot, "public");

const OUT_ASSETS_FOLDER = "assets"; // 指定生成静态资源的存放路径 (相对于 build.outDir); default = "assets"
// ----------------------------------------------------------------------------
/**
 * 装载自定义环境信息
 * @param mode 在 package.json 文件 scripts 中定义的 `NODE_ENV`
 * @param envPath env 文件路径
 * @returns Vite Env 信息 {@link ViteEnv}
 * @description 根据在 package.json 文件 scripts 中定义的 `NODE_ENV`
 * 选择自定义环境信息文件 (.env & .env.development || .env.production || .env.test)
 */
function loadViteEnv(mode: string, envPath: string): ViteEnv {
    //
    const result: Record<string, any> = {};
    // const result: Partial<ViteEnv> = {}
    // ----------------------------------------------------
    // 根据 process.env.NODE_ENV 选择装载 envDir 目录下面的
    // NODE_ENV = development | production | test 等
    // 根据当前工作目录中的 `mode` 加载 .env 文件
    // env 文件 (.env.development / .env.production / .env.test)
    // 设置第三个参数为 "" 来加载所有环境变量，而不管是否有`VITE_` 前缀。
    const _env = loadEnv(mode, envPath, "") as Record<string, any>;

    // 解析数据
    for (const env_key of Object.keys(_env)) {
        //
        let env_value = _env[env_key].replace(/\\n/g, "\n");

        // 转换 boolean 类型
        env_value = env_value === "true" ? true : env_value === "false" ? false : env_value;

        // 转换 number 类型
        if (env_key === "VITE_PORT") {
            env_value = Number(env_value);
        }

        // 代理服务器
        if (env_key === "VITE_PROXY") {
            try {
                env_value = JSON.parse(env_value);
            } catch (error) {
                // throw error;
            }
        }

        //
        result[env_key] = env_value;
    }
    // ----------------------------------------------------
    return result as ViteEnv;
}
// ----------------------------------------------------------------------------
/**
 * 构造 UserConfig
 * @param mode - Which type is {@link String} = "development" | "production",
 * @returns
 */
function buildUserConfig(mode: string): UserConfig {
    const MODE = mode ?? "development";
    const isDevelopment = MODE === "development";
    const viteEnv = loadViteEnv(MODE, EnvDir);
    // console.log(mode)
    // console.log(isDevelopment)
    //
    const result: UserConfig = {
        appType: "spa", // APP 类型
        root: AppRoot, // 项目根目录（index.html 文件所在的位置）
        envDir: EnvDir, // 环境文件(.env.*)目录
        cacheDir: CacheDir, // 存储缓存文件的目录
        publicDir: PublicDir, // 静态资源服务的文件夹, 在构建期间复制到 build.outDir 的根目录
        mode: MODE, // be overridden by the command line --mode option.
        assetsInclude: [], // 包含的资产

        resolve: {
            alias: {
                ["#"]: SRC,
                ["vue"]: "vue/dist/vue.esm-bundler.js",
                ["vue-i18n"]: "vue-i18n/dist/vue-i18n.cjs.js", // 解决i8n警告 ...vue-i18n.esm-bundler.js
            },
            // 导入时想要省略的扩展名列表
            extensions: [".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx", ".json"],
        },

        // Vite 内置支持 `Sass`、`Less` 和 `Stylus` 等 CSS 预处理器。
        css: {
            // CSS 模块化
            modules: {
                scopeBehaviour: "local", // 使用局部作用域 ['global' | 'local']
                generateScopedName: "[name]_[local]_[hash:base64:6]", // 自定义类名格式
                // hashPrefix: "prefix", // 哈希前缀
                // globalModulePaths: [], // 排除全局 CSS 文件, 指定哪些文件不启用 CSS Modules。
            },
            // CSS 预处理器的选项 (Vite 内置支持 `Sass`、`Less` 和 `Stylus`)
            preprocessorOptions: {
                scss: {
                    // 隐藏如下警告:
                    // Deprecation Warning: The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
                    api: "modern-compiler", // 'legacy' | 'modern' | 'modern-compiler'
                    // additionalData: `@import "#/styles/variables.module.scss";`, // 全局引入变量文件
                    // additionalData: `@use "#/styles/element/index.scss" as *;`, // or
                    // javascriptEnabled: true, // 支持内联 JavaScript
                },
                less: {
                    // 预编译支持less
                    // additionalData: '@import "#/styles/variables.module.less";',
                    // javascriptEnabled: true, // 支持内联 JavaScript
                    // math: "parens-division", // Less 数学计算模式
                },
            },
            // Vite 默认集成了 PostCSS
            postcss: {
                plugins: [
                    // require("autoprefixer")({
                    //     overrideBrowserslist: ["last 2 versions", "> 1%"], // 浏览器兼容范围
                    // }),
                ],
            },
            // CSS sourcemaps enabled during dev
            devSourcemap: true,
            // CSS 转换器 => 'postcss' | 'lightningcss' default = 'postcss'
            transformer: "postcss",
        },

        plugins: [
            vue(),
            vueJsx(),
            vueDevTools(),
            // AutoImport({
            //     imports: ["vue"],
            //     dts: "src/autotypes/auto-imports.d.ts",
            //     resolvers: [ElementPlusResolver()],
            // }),
            // Components({
            //     dts: "src/autotypes/auto-components.d.ts",
            //     resolvers: [
            //         // 自动导入 Element Plus 组件
            //         ElementPlusResolver({ importStyle: "sass" }),
            //     ],
            // }),
            // 按需导入图标
            // Icons(),
            // HTML
            // createHtmlPlugin({
            //     minify: true,
            //     inject: {
            //         data: {
            //             app_title: viteEnv.VITE_APP_TITLE,
            //         },
            //     },
            // }),
            // 使用本地 svg 作为图标 icon
            // createSvgIconsPlugin({
            //     iconDirs: SvgIconDirs,
            //     symbolId: "icon-[dir]-[name]",
            // }),
            // 静态资源拷贝
            // viteStaticCopy({
            //     targets: [{ src: ["LICENSE"], dest: "" }],
            // }),
        ],

        /** Server Options */
        server: {
            host: "0.0.0.0", // 项目运行地址，此处代表 localhost
            port: viteEnv.VITE_PORT, // 项目运行端口 default = 5173 ()
            open: viteEnv.VITE_OPEN, // 运行 npm run dev 时是否自动打开浏览器
            hmr: viteEnv.VITE_HMR, // 是否开启热加载
            strictPort: false, // 设为 true 时若端口已被占用则会直接退出
            https: undefined, // 启用 TLS + HTTP/2
            cors: true, // 默认启用并允许任何源
            proxy: undefined, // 跨域代理配置,期望接收一个 { key: options }
        },

        build: {
            outDir: OutDir, // 指定输出路径, 默认 dist
            minify: isDevelopment ? false : "esbuild", // specify the minifier to use
            assetsDir: OUT_ASSETS_FOLDER, // 指定生成静态资源的存放路径 (相对于 build.outDir)
            cssCodeSplit: true, // 配置 CSS 代码拆分
            sourcemap: false, // 构建后是否生成 source map 文件, default false
            manifest: true, // 构建后将会生成 manifest.json 文件, 默认 false (OUT/.vite/manifest.json)
            copyPublicDir: true, // 在构建阶段将 public 目录中的所有文件复制到 outDir 目录中
            chunkSizeWarningLimit: 1500, // 调整区块大小警告限制 (in kbs).
            rollupOptions: {
                input: undefined, // /path/to/your/index.html
                // 自定义底层的 Rollup 打包配置
                output: {
                    entryFileNames: `${OUT_ASSETS_FOLDER}/js/entry-[name]-[hash].js`,
                    chunkFileNames: `${OUT_ASSETS_FOLDER}/js/chunk-[name]-[hash].js`,
                    assetFileNames: `${OUT_ASSETS_FOLDER}/[ext]/[name]-[hash].[ext]`,
                    // https://rollupjs.org/guide/en/#outputmanualchunks
                    manualChunks: {
                        // "group-hooks": ["./src/hooks"],
                        // "group-widgets": ["./src/widgets"],
                        // "group-utils": ["./src/utils"],
                    },
                },
                external: [],
            },
        },

        esbuild: {
            // 打包去除 console.log 等调式信息
            pure: viteEnv.VITE_DROP_CONSOLE ? ["console.log", "console.trace"] : [],
        },

        // 自定义
        define: {
            DEMO_BOOL: true,
            DEMO_NUMBER: 20,
            DEMO_ARRAY: [1, 2, 3],
            DEMO_OBJECT: { name: "asc" },
            DEMO_STRING: JSON.stringify("This is demo string..."),
        },
    };

    return result as UserConfig;
}
// ----------------------------------------------------------------------------
const userConfig = (config: ConfigEnv) => buildUserConfig(config.mode);
export default defineConfig(userConfig) as UserConfig;
// ----------------------------------------------------------------------------
